package edu.neusoft.yiqibike.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.collect.ImmutableMap;
import edu.neusoft.yiqibike.common.cache.redis.IRedisHelper;
import edu.neusoft.yiqibike.common.constant.RedisConstant;
import edu.neusoft.yiqibike.common.datasource.TargetDataSource;
import edu.neusoft.yiqibike.common.entity.mysql.IpRecord;
import edu.neusoft.yiqibike.common.entity.mysql.OperationLog;
import edu.neusoft.yiqibike.common.entity.vo.IpRecordVo;
import edu.neusoft.yiqibike.common.util.MapperUtil;
import edu.neusoft.yiqibike.dao.mapper.IpRecordMapper;
import edu.neusoft.yiqibike.service.IPManagerService;
import org.apache.commons.collections.MapUtils;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import qiniu.happydns.util.IP;

import java.lang.annotation.Target;
import java.util.*;
import java.util.stream.Collectors;

/**
 * User：lyc
 * Date：2017-12-16
 * Time：21:08
 * Description：
 */
@Service
public class IPManagerServiceImpl extends ServiceImpl<IpRecordMapper, IpRecord> implements IPManagerService {
    @Autowired
    private IRedisHelper redisHelper;

    /**
     * 优化前
     * FIXME 查询速度慢—SQL优化
     *
     * @param page
     * @return
     */
    @Override
    @TargetDataSource(name = "ds2")
    public Page<IpRecordVo> getIPList(Page<IpRecord> page) {
        List<IpRecordVo> records = null;
        Wrapper<Object> condition = new EntityWrapper<>();
        if (Objects.nonNull(page) && !CollectionUtils.isEmpty(page.getCondition())) {
            condition = condition.allEq(page.getCondition());
        }
        List<IpRecord> ipRecords = baseMapper.selectByPage(page, condition);
        if (!CollectionUtils.isEmpty(ipRecords)) {
            records = new ArrayList<>();
            for (IpRecord record : ipRecords) {
                if (Objects.nonNull(record)) {
                    OperationLog operationLog = new OperationLog();
                    int count = operationLog.selectCount(new EntityWrapper().eq("ip", record.getIp()));
                    operationLog = operationLog.selectOne(new EntityWrapper().eq("ip", record.getIp())
                            .orderBy("create_time", false));
                    //使用dozer进行数据转换
                    IpRecordVo recordVo = MapperUtil.getInstance().map(record, IpRecordVo.class);
                    recordVo.setAccessCount(count);
                    if (Objects.nonNull(operationLog)) {
                        recordVo.setLocation(operationLog.getLocation());
                        recordVo.setLastAccessTime(operationLog.getCreateTime());
                    }
                    records.add(recordVo);
                }
            }
        }
        Page<IpRecordVo> voPage = new Page<>();
        MapperUtil.getInstance().map(page, voPage);
        voPage.setRecords(records);
        return voPage;
    }

    /**
     * 优化后
     * @param page
     * @return
     */
    @Override
    @TargetDataSource(name = "ds2")
    public Page<IpRecordVo> getHideIPList(Page<IpRecordVo> page) {
        List<IpRecordVo> ipRecords = baseMapper.selectHideIpList(page);
        //虚拟活跃状态，实际数据库中不存在0的值
        for (IpRecordVo vo : ipRecords) {
            if (vo.getIsEnable() == 1) {
                vo.setIsEnable(0);
            }
        }
        page.setRecords(ipRecords);
        return page;
    }

    @Override
    @Transactional
    @TargetDataSource(name = "ds2")
    public void invertIsEnable(String id, Integer isEnable) {
        IpRecord ipRecord = baseMapper.selectOneById(id);
        if (isEnable != 1 && isEnable != -1) {
            throw new IllegalArgumentException("【IP可用状态】：非法");
        }
        isEnable = ipRecord.getIsEnable();
        if (isEnable == 1) {
            isEnable = -1;
        } else if (isEnable == -1) {
            isEnable = 1;
        }
        baseMapper.updateIsEnableById(id, isEnable);
        this.syncRedis(ipRecord.getIp(), isEnable);
    }

    /**
     * IP备案拉黑
     *
     * @param ip IP地址
     */
    @Override
    @Transactional
    @TargetDataSource(name = "ds2")
    public void addIP(String ip) {
        Integer isEnable = -1;
        IpRecord ipRecord = new IpRecord();
        ipRecord.setCreateTime(new Date());
        ipRecord.setIp(ip);
        ipRecord.setIsEnable(isEnable);
        ipRecord.insert();
        this.syncRedis(ip, isEnable);
    }

    @Override
    @Transactional
    @TargetDataSource(name = "ds2")
    public void deleteBatch(List<String> ids) {
        baseMapper.deleteBatchByIds(ids);
    }

    /**
     * 将MySQL状态同步至Redis
     *
     * @param ip       IP地址
     * @param isEnable 可用标志
     */
    private void syncRedis(String ip, Integer isEnable) {
        Map<String, Integer> ipMap = redisHelper.getHmap(RedisConstant.IP_LIMIT_PREFIX + ip);
        if (MapUtils.isEmpty(ipMap)) {
            ipMap = new HashMap<>();
            ipMap.put("count", 0);
        }
        ipMap.put("flag", isEnable);
        redisHelper.setHmap(RedisConstant.IP_LIMIT_PREFIX + ip, ipMap);
    }
}
